package com.cdel.akka.statuschange;

import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.Procedure;

//很多场景下，actor的业务逻辑可能比较复杂，actor可能需要根据不同的状态对同一条消息作出不同的处理。yigeactor内部消息处理函数可以拥有多个不同的状态，在特定状态下，可以对同一个消息进行不同的处理，状态之间也可以任意切换。
public class BabyActor extends UntypedActor {

	private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);

	public static enum Msg{
		SLEEP, PLAY, CLOSE;
	}

	Procedure<Object> angry = new Procedure<Object>() {
		@Override
		public void apply(Object message) throws Exception {
			System.out.println("angryApply:" + message);
			if(message == Msg.SLEEP){
				getSender().tell("i am already angry", getSelf());
				System.out.println("i am already angry");
			}else if(message == Msg.PLAY){
				System.out.println("i like playing");
				getContext().become(happy);
			}
		}
	};

	Procedure<Object> happy = new Procedure<Object>() {
		@Override
		public void apply(Object message) throws Exception {
			System.out.println("happyApply:" + message);
			if(message == Msg.PLAY){
				getSender().tell("i am already happy :-)", getSelf());
				System.out.println("i am already happy :-)");
			}else if(message == Msg.SLEEP){
				System.out.println("i dont't want to sleep");
				getContext().become(angry);
			}
		}
	};

	@Override
	//在初始状态时，BabyActor没有生气也没有高兴，因此angry、happy处理函数都不会工作。当BabyActor接收到消息时，系统会调用onReceive来处理消息。
	public void onReceive(Object msg) throws Throwable {
		System.out.println("onReceive:" + msg);
		//当onReceive处理sleep消息时，它会切换当前actor状态为angry；如果是play消息，则切换为happy。
		//一旦切换完成，后续消息就不会再由onReceive函数处理了，由于angry、happy本身就是消息处理函数。因此后续的消息就直接交由当前状态处理(angry、happy)，从而很好的封装了actor的多个不同处理逻辑。
		if(msg == Msg.SLEEP){
			getContext().become(angry);
		}else if(msg == Msg.PLAY){
			getContext().become(happy);
		}else{
			unhandled(msg);
		}
	}

}
